package com.yang.sms;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yang.common.amqp.MessageSender;
import com.yang.common.core.util.Utils;
import com.yang.sms.dto.MobileTemplateParam;
import com.yang.sms.dto.SendSmsMQDto;
import com.yang.sms.entity.SmsTask;
import com.yang.sms.entity.SmsTaskDetail;
import com.yang.sms.enums.Constants;
import com.yang.sms.enums.SmsEnum;
import com.yang.sms.enums.SmsTaskDetailEnum;
import com.yang.sms.service.SmsTaskDetailService;
import com.yang.sms.service.SmsTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 短信发送器(异步)
 *
 * @author Billyang
 * @date 2024/9/26 18:08
 */
@Component
public class AsyncSmsSender {

    @Autowired
    private MessageSender messageSender;

    @Autowired
    private SmsTaskService smsTaskService;

    @Autowired
    private SmsTaskDetailService smsTaskDetailService;

    public void send0(List<String> mobileList, SmsEnum.Type type) {
        Map<String, String> emptyMap = Maps.newHashMap();
        List<MobileTemplateParam> mobileTemplateParamList = mobileList.stream().map(mobile -> {
            MobileTemplateParam mobileTemplateParam = new MobileTemplateParam();
            mobileTemplateParam.setMobile(mobile);
            mobileTemplateParam.setTemplateParamMap(emptyMap);
            return mobileTemplateParam;
        }).collect(Collectors.toList());
        send(mobileTemplateParamList, type);
    }

    public void send(List<MobileTemplateParam> mobileTemplateParamList, SmsEnum.Type type) {
        LocalDateTime planSendTime = LocalDateTime.now();
        LocalDateTime overTime = planSendTime.plusDays(1);
        send(mobileTemplateParamList, type, planSendTime, overTime);
    }

    public void send(String mobile, SmsEnum.Type type) {
        LocalDateTime planSendTime = LocalDateTime.now();
        LocalDateTime overTime = planSendTime.plusDays(1);
        send(mobile, Maps.newHashMap(), type, planSendTime, overTime);
    }

    public void send(String mobile, SmsEnum.Type type, LocalDateTime planSendTime, LocalDateTime overTime) {
        send(mobile, Maps.newHashMap(), type, planSendTime, overTime);
    }

    public void send(String mobile, Map<String, String> templateParamMap, SmsEnum.Type type, LocalDateTime planSendTime,
                     LocalDateTime overTime) {
        MobileTemplateParam mobileTemplateParam = new MobileTemplateParam();
        mobileTemplateParam.setMobile(mobile);
        mobileTemplateParam.setTemplateParamMap(templateParamMap);
        send(mobileTemplateParam, type, planSendTime, overTime);
    }

    public void send(MobileTemplateParam mobileTemplateParam, SmsEnum.Type type, LocalDateTime planSendTime,
                     LocalDateTime overTime) {
        send(Lists.newArrayList(mobileTemplateParam), type, planSendTime, overTime);
    }

    public void send(List<MobileTemplateParam> mobileTemplateParamList, SmsEnum.Type type, LocalDateTime planSendTime,
                     LocalDateTime overTime) {
        SmsTask smsTask = new SmsTask();
        smsTask.setType(type.getCode());
        smsTask.setPlanSendTime(planSendTime);
        smsTask.setOverTime(overTime);
        smsTask.setRemark("AsyncSmsSender-" + DateUtil.format(new Date(), "yyMMddHHmmss"));
        smsTaskService.insert(smsTask);

        for (MobileTemplateParam templateParam : mobileTemplateParamList) {
            SmsTaskDetail smsTaskDetail = new SmsTaskDetail();
            smsTaskDetail.setTaskId(smsTask.getId());
            smsTaskDetail.setMobile(templateParam.getMobile());
            smsTaskDetail.setTemplateParamJson(JSON.toJSONString(templateParam.getTemplateParamMap()));
            smsTaskDetail.setPlanSendTime(planSendTime);
            boolean sendNow = planSendTime.compareTo(LocalDateTime.now()) <= 0;
            SmsTaskDetailEnum.Status status = sendNow ? SmsTaskDetailEnum.Status.WAIT_SEND : SmsTaskDetailEnum.Status.WAIT_PLAN_SEND;
            smsTaskDetail.setStatus(status.getCode());
            smsTaskDetailService.insert(smsTaskDetail);
            if (sendNow) {
                asyncSend(smsTaskDetail.getId(), status);
            }
        }
    }

    /**
     * 会有定时任务轮询处理
     */
    public List<Integer> select4PreTimeSend(int limit) {
        return smsTaskDetailService.select4PreTimeSend(SmsTaskDetailEnum.Status.WAIT_PLAN_SEND, limit);
    }

    /**
     * 定时任务轮询到待发送的短信后，调用这个方法异步发送短信
     */
    public void exePreTimeSend(Integer id) {
        asyncSend(id, SmsTaskDetailEnum.Status.WAIT_PLAN_SEND);
    }

    private void asyncSend(Integer smsTaskDetailId, SmsTaskDetailEnum.Status status) {
        //MQ异步处理
        SendSmsMQDto params = new SendSmsMQDto();
        params.setSmsTaskDetailId(smsTaskDetailId);

        messageSender.sendNormalMessage(null, params, Constants.EXCHANGE.DIRECT,
                Constants.QUEUE.SEND_SMS.ROUTING_KEY);

        //必须加状态条件，消费者代码可能会比下面的代码先执行
        SmsTaskDetail smsTaskDetail = smsTaskDetailService.selectById(smsTaskDetailId);
        String remark = Utils.rightRemark(smsTaskDetail.getRemark(), SmsTaskDetailEnum.Status.SEND_MQ_SUCCESS.getDesc());
        smsTaskDetailService.updateStatusByStatus(SmsTaskDetailEnum.Status.SEND_MQ_SUCCESS, remark, smsTaskDetailId, status);
    }


}
